/*
 * Galaxium Messenger
 * 
 * Copyright (C) 2007 Paul Burton <paulburton89@gmail.com>
 * 
 * License: GNU General Public License (GPL)
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

using System;
using System.IO;
using System.Text;

using Anculus.Core;

using Galaxium.Core;

namespace Galaxium.Protocol.Msn
{
	public enum FTType : uint
	{
		NoPreview          = 1,
		Background         = 4,
		Unknown            = 8     // Animated?
	}
	
	public class FTContext
	{
		uint _version = 3;
		ulong _fileSize = 0;
		FTType _type = FTType.NoPreview;
		string _filename = string.Empty;
		byte[] _unknown1 = new byte[0];
		uint _unknown2 = 0xFFFFFFFF; //0xFFFFFFFE for backgrounds
		byte[] _unknown3 = new byte[54];
		byte[] _preview = new byte[0];
		
		public uint Version
		{
			get { return _version; }
		}
		
		public ulong FileSize
		{
			get { return _fileSize; }
		}
		
		public FTType Type
		{
			get { return _type; }
		}
		
		public string Filename
		{
			get { return _filename; }
		}
		
		public byte[] Preview
		{
			get { return _preview; }
		}
		
		public FTContext (byte[] data)
		{
			MemoryStream stream = new MemoryStream (data);
			BinaryReader reader = new BinaryReader (stream);
			
			uint _headerLen = (uint)BitUtility.ToInt32 (reader.ReadBytes (4), 0, false);
			_version = (uint)BitUtility.ToInt32 (reader.ReadBytes (4), 0, false);
			_fileSize = (ulong)BitUtility.ToInt64 (reader.ReadBytes (8), 0, false);
			_type = (FTType)BitUtility.ToInt32 (reader.ReadBytes (4), 0, false);
			_filename = Encoding.Unicode.GetString (reader.ReadBytes (520)).Replace ("\0", "").Trim ();
			//_unknown1 = Convert.FromBase64String (Encoding.Unicode.GetString (reader.ReadBytes (30)));
			//_unknown2 = (uint)BitUtility.ToInt32 (reader.ReadBytes (4), 0, false);
			
			ThrowUtility.ThrowIfTrue (string.Format ("{0} < {1}", data.Length, _headerLen), data.Length < _headerLen);
			
			_preview = new byte[data.Length - _headerLen];
			if (_preview.Length > 0)
				Array.Copy (data, _headerLen, _preview, 0, _preview.Length);
			
			reader.Close ();
			stream.Close ();
		}
		
		public FTContext (string filename, ulong filesize)
		{
			_filename = filename;
			_fileSize = filesize;
		}
		
		public byte[] ToByteArray ()
		{
			int length = 638 + _preview.Length;
			
			byte[] data = new byte[length];
			MemoryStream stream = new MemoryStream (data);
			BinaryWriter writer = new BinaryWriter (stream);
			
			writer.Write (BitUtility.FromInt32 (length, false));
			writer.Write (BitUtility.FromInt32 ((int)_version, false));
			writer.Write (BitUtility.FromInt64 ((long)_fileSize, false));
			writer.Write (BitUtility.FromInt32 ((int)_type, false));
			writer.Write (Pad (Encoding.Unicode.GetBytes (_filename), 520));
			writer.Write (Pad (_unknown1, 30));
			writer.Write (BitUtility.FromInt32 ((int)_unknown2, false));
			writer.Write (_unknown3);
			
			if (_preview.Length > 0)
				writer.Write (_preview);
			
			writer.Close ();
			stream.Close ();
			
			return data;
		}
		
		byte[] Pad (byte[] data, uint len)
		{
			byte[] ret = new byte[len];
			Array.Copy (data, ret, data.Length);
			return ret;
		}
	}
}
